package com.kaguya.interpreter;

import com.sun.org.apache.xpath.internal.operations.Or;

import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.List;
import java.util.StringTokenizer;

/**
 * 解释器模式，用于对一些固定语法构建解释句子的解释器
 * 容易改变和扩展文法，比较容易实现文法
 * 类容易膨胀，可用场景较少
 */
public class Test {
    public static void main(String[] args) {
        Expression expression = buildExpression();
        List<String> strs = Arrays.asList("D A","D B","D C","D B C","D D","B D","A B","D D A C");

        for (String str : strs) {
            System.out.println(str+ " ||matching :" + expression.interpret(str));
        }
    }

    /**
     * 构建解释器规则，字符串 满足 特定条件
     * @return
     */
    public static Expression buildExpression() {
        System.out.println("rule: D and (A or (B or C))");
        // literal
        Expression terminalA = new TerminalExpression("A");
        Expression terminalB = new TerminalExpression("B");
        Expression terminalC = new TerminalExpression("C");
        Expression terminalD = new TerminalExpression("D");
        // B or C
        Expression matchOr1 = new OrExpression(terminalB,terminalC);
        // A or (B or C)
        Expression matchOr2 = new OrExpression(terminalA,matchOr1);
        // D and (A or (B or C))
        Expression matchAnd = new AndExpression(terminalD,matchOr2);

        return matchAnd;
    }
}

/**
 * 解释器抽象类
 */
abstract class Expression {
    public abstract boolean interpret(String str);
}

/**
 * 包含解释器 构建时的str 与后续的串包含即返回true，例如new TerminalExpression("B") interpret("ABC") 返回true
 */
class TerminalExpression extends Expression {

    private String literal = null;

    public TerminalExpression(String str) {
        literal = str;
    }

    @Override
    public boolean interpret(String str) {
        StringTokenizer stringTokenizer = new StringTokenizer(str);
        while(stringTokenizer.hasMoreTokens()) {
            String text = stringTokenizer.nextToken();
            if(text.equals(literal)) {
                return true;
            }
        }
        return false;
    }
}

/**
 * and 规则解释器，两个包含解释器都满足
 */
class AndExpression extends Expression {

    private Expression expression1 = null;
    private Expression expression2 = null;

    public AndExpression(Expression expression1, Expression expression2) {
        this.expression1 = expression1;
        this.expression2 = expression2;
    }

    @Override
    public boolean interpret(String str) {
        return expression1.interpret(str) && expression2.interpret(str);
    }
}

/**
 * or 规则解释器 只需满足其中一个解释器你
 */
class OrExpression extends Expression {

    private Expression expression1 = null;
    private Expression expression2 = null;

    public OrExpression(Expression expression1, Expression expression2) {
        this.expression1 = expression1;
        this.expression2 = expression2;
    }

    @Override
    public boolean interpret(String str) {
        return expression1.interpret(str) || expression2.interpret(str);
    }
}